Design System — v1.0

One visual language
across every page.

The source of truth for every design token used on this portfolio. Colors, typography, spacing, radius, motion — all documented here as they ship in production. Covers desktop, tablet, and mobile behavior.

All previews are live CSS — what you see on this page is what the site uses.

Color tokens

11 semantic color tokens. Every color on the site belongs to one of these groups — surface, text, brand, border, or semantic state. No hardcoded hex values in page CSS.

11 tokens

Semantic names, clear hierarchy

Each token has a single purpose. Names describe intent ("text-secondary"), not position ("muted2"). Backgrounds collapsed to 3 levels that actually differ visually.

Surface — 3 levels

--surface-base#0F1412Page background
--surface-raised#1A201DSections, cards
--surface-overlay#252B28Modals, nav blur

Text — 3 tiers of emphasis

--text-primary#FFFFFFHeadings, body
--text-secondarywhite/72%Descriptions
--text-tertiarywhite/48%Metadata, labels

Brand — accent only

--accent#FFC321Brand, CTAs
--accent-hover#FFD658Hover states

Borders — 2 levels

--border-subtlewhite/8%Divider lines
--border-defaultwhite/14%Inputs, cards

Semantic states

--state-error#FF6B6B
--state-success#34D399
Rationale: Every token has a single purpose. The three surface levels have noticeable contrast so raised cards actually look raised. Error and success are tokenized so they never get hardcoded.

Type scale

Two font families (Outfit for headings, Inter for body) on a 1.25× modular scale. Every heading and body size is one of the 9 tokens below. Scales automatically across desktop, tablet, and mobile.

2 fonts, 9 sizes

Two fonts, modular scale (1.25 ratio)

Outfit handles all headings. Inter handles all body. 9 sizes cover every use case, each built on the perfect-fourth modular scale (1.25×).

Display Display Outfit 500 / 72px
H1 Page Title Outfit 500 / 56px
H2 Section Outfit 500 / 44px
H3 Subsection Outfit 500 / 32px
H4 Card title Outfit 500 / 22px
Body L Large body for hero & long-form Inter 400 / 18px
Body Default paragraph text Inter 400 / 16px
Small Metadata, captions Inter 500 / 14px
Eyebrow Eyebrow Label Outfit 500 / 12px
Rationale: Body defaults to weight 400 (regular) for better readability on long text. Medium (500) is reserved for UI, headings, and small/caption text where extra weight aids legibility. Removing Heebo saves ~35KB of font weight and simplifies visual identity.

Responsive scale per breakpoint

TokenDesktopTabletMobile
Display72px56px40px
H156px44px32px
H244px36px28px
H332px28px24px
H422px20px18px
Body L18px17px16px
Body16px16px15px
Small14px14px13px
Eyebrow12px12px11px

Roundness scale

Sharp corners everywhere. Rounded rectangles dilute the editorial tone, so every button, card, input, chip, and panel uses 0 radius. The only exception: inherently circular shapes (avatars, swatches, dot indicators).

2 values only

Sharp corners, period.

No rounded rectangles anywhere — buttons, cards, inputs, chips, modals all use 0. The only radius allowed is --radius-full (999px) for inherently circular shapes (avatars, color swatches, dot indicators).

none
0
full
999px

Usage mapping

TokenValueWhere
--radius-none0Everything — buttons, cards, inputs, images, modals, filter chips, badges, section panels
--radius-full999pxAvatars, color swatches, dot indicators (only inherently round shapes)
Rationale: Editorial identity is built on confident geometry. Rounded rectangles dilute that tone. By committing to 0 for every rectangle, the site feels like it was designed on paper with a straight-edge — every corner is intentional. Circles are reserved for things that are genuinely circular in the real world.

Spacing & padding scale

Every spacing value should belong to a predictable scale. The 8-point grid is the industry standard and works here because it aligns cleanly with the type scale.

8-point scale

Every value is a multiple of 4

Named scale from xs to 5xl. Use tokens, not hardcoded pixels. Scales automatically across breakpoints.

--space-xs
4px
--space-sm
8px
--space-md
16px
--space-lg
24px
--space-xl
32px
--space-2xl
48px
--space-3xl
64px
--space-4xl
96px
--space-5xl
128px

Section padding per breakpoint

TypeDesktopTabletMobile
Horizontal (--pad)96px48px24px
Section vertical96px64px48px
Compact section64px48px32px
Card padding24px20px16px
Button padding12px 24px12px 20px10px 16px
Rationale: Every size is divisible by 4, so components line up naturally on a grid. Scale ratio of ~1.5x between tokens means each step feels meaningful. Developer/designer picks from a known list instead of inventing values.

Button system

One CTA pattern across the entire site: uppercase text with a trailing arrow. Hover triggers the per-letter flip (white → accent yellow) with staggered delay. No backgrounds, no borders. Filter chips are the only exception (needed for group-toggle UX).

text-only, one system

No boxes. Letters + motion.

One CTA pattern across the site: uppercase text with a trailing arrow. Hover triggers the per-letter flip (white → accent yellow) with staggered delay. No backgrounds, no borders, no pill-vs-solid debates.

Default CTA — hover me

Used for every primary action across the site: Send Message, View All, View Case Study, Next Project, etc. Text is always UPPERCASE. Arrow on the right slides 4px on hover. Each letter flips to accent yellow on hover with 20ms per-character stagger.

Disabled state

Faded white, no hover, arrow dimmed. Pointer-events disabled so hover animation doesn't fire.

Filter chip

Rectangular outlined chip for togglable filter groups. Sharp corners match the rest of the system. Active state: accent border and accent text, no fill.

CTA specs across breakpoints

PropertyDesktopTabletMobile
Font size15px15px14px
Letter spacing.5px.5px.5px
Arrow spacing (rest)10px10px8px
Arrow spacing (hover)14px14px12px
Letter flip duration250ms250ms250ms
Letter stagger20ms/char20ms/char20ms/char
Rationale: A portfolio reads better without box-heavy UI. Text-only CTAs let the writing carry the hierarchy; motion carries the affordance. The per-letter flip is distinctive to this site — it's the signature interaction. Only filters (which need to show active state in a group) use a box.

Input fields & form elements

Inputs should feel like part of the same family as buttons — same radius, same padding math, same focus ring.

sharp, tokenized

Zero radius. Clean focus state.

Inputs match the rest of the system: sharp corners, subtle border. Focus turns the border accent yellow. Error state uses the --state-error token with a faint background tint.

Enter a valid email address

Rationale: Inputs feel like part of the editorial page, not a separate UI layer. Focus ring is always accent color — predictable. Error state uses --state-error + 4% background tint for soft context.

Icon buttons & navigation arrows

Icon buttons are used for navigation (carousel arrows, lightbox prev/next) and utility actions (close, menu). They need their own consistent style because text-only CTAs don't work when there's no text.

one icon button

Sharp square. 2px border. Accent on hover.

Every icon button shares the exact same shell. Two sizes (default 56×56, small 44×44). Same border, same hover state, same active press.

Default — 56×56 (carousel, lightbox arrows)

Small — 44×44 (mobile arrows, compact UI)

Shared specs

PropertyDefaultSmall
Size56×5644×44
Border2px solid #3239362px solid #323936
Backgroundtransparenttransparent
Icon size18×1814×14
Stroke width2px2px
Hoverborder-color → --accentborder-color → --accent
Activeborder-width 1px + scale(.96)border-width 1px + scale(.96)
Focus-visibleoutline 2px --accent · offset 2pxoutline 2px --accent · offset 2px

Used for

ContextSizeWhere
Testimonial carousel56pxHomepage testimonials prev/next
Lightbox arrows56px (44px mobile)Case study image zoom prev/next
Lightbox close48pxCase study image zoom top-right
Burger menu44pxMobile navbar
Rationale: One visual language for every non-text interactive control. Users learn "square with border = clickable icon." The hover state (border turns accent) is the same affordance signal used everywhere else on the site.

Card system

One card pattern for every context — blog posts, case studies, project grid, metrics, testimonials, value props. Sharp corners, subtle border, consistent hover behavior (lift + thumbnail zoom + title shifts to accent).

one card, sharp

One card pattern. Zero radius.

Every card on the site shares the same shell: sharp corners, subtle border, thumbnail on top, content below. Used by blog posts, case studies, value props, testimonials, metrics — all the same.

📰

Project / Blog

Image + title + description. Hover lifts 4px, thumbnail zooms 1.04x, title shifts to accent.

📊

Metric / Value

Same shell, text-only content. Used for stats, testimonials, value propositions.

Shared behavior

AttributeValue
Border radius0
Background--surface-raised
Border1px solid --border-subtle
Padding (desktop)24px
Padding (tablet)20px
Padding (mobile)16px
Hover lifttranslateY(-4px) · 350ms · --ease-out
Image zoomscale(1.04) · 500ms · --ease-out
Title on hovercolor → --accent · 250ms
Rationale: One card shape across the whole site. Users instantly recognize "this is a card" regardless of what's inside it. Sharp corners keep the editorial, confident tone.

Responsive behavior

Three breakpoints covering every device — Mobile (< 640px), Tablet (640–1024px), Desktop (> 1024px). Every token scales predictably at these three tiers.

3 breakpoints

Mobile · Tablet · Desktop

Three clear tiers aligned to actual devices.

📱

Mobile

< 640px

Single column, stacked nav hidden behind hamburger, 24px side padding, tightest type scale.

📲

Tablet

640 – 1024px

2-column grids where possible, nav still hamburger, 48px side padding, medium type scale.

💻

Desktop

> 1024px

Full multi-column layouts, horizontal nav visible, 96px side padding, full type scale.

Example — Hero heading scale

Mobile

< 640px

I Design Solutions.

Hello there, I am Shreyansh Gaurav.

Tablet

640 – 1024px

I Design Solutions.

Hello there, I am Shreyansh Gaurav.

Desktop

> 1024px

I Design Solutions.

Hello there, I am Shreyansh Gaurav.

Rationale: 3 breakpoints cover 99% of devices. Mobile-first media queries (min-width) make intent clear. Less CSS overall, predictable behavior on every device.

Animation & easing

Motion is part of the brand. 5 duration tokens + 4 easing tokens power every animation on the site — from hover states to scroll-triggered reveals.

5 durations · 4 easings

Tokenized motion scale

Every animation picks from a short list. One token per intent (hover, reveal, long-form, marquee).

Duration tokens

TokenValueUse
--duration-instant100msButton press, focus ring
--duration-fast200msHover states (color, border, shadow)
--duration-base350msCard lift, image zoom, nav slide
--duration-slow600msHeading reveals (gravity drop)
--duration-longform1800msBody per-line wave reveal

Easing tokens

--ease-out

cubic-bezier(.22, 1, .36, 1)

Default. Reveals, hovers, anything entering view.

--ease-smooth

cubic-bezier(.19, 1, .22, 1)

Long-form body reveals. Gentlest exit curve.

--ease-spring

cubic-bezier(.34, 1.56, .64, 1)

Playful overshoot. Use sparingly (1–2 moments per page).

--ease-linear

linear

Marquees, spinners, infinite loops only.

Rationale: 5 durations, 4 easings. Every new animation must pick from this list — no custom values. Reduces visual noise and keeps the site feeling handcrafted rather than auto-generated.

Named motion patterns

The five animations we use sitewide, documented and demoed.

Pattern 01 — Heading Reveal

Gravity Drop · per-letter

Applied to every yellow primary heading across the site (homepage sections, case study titles, blog post titles, contact, about). Letters drop in from above with a subtle bounce.

Live demo

Project Overview

PropertyValue
Duration600ms (--duration-slow)
Easingcubic-bezier(.22, 1, .36, 1) + overshoot keyframes
Stagger50ms per character
TriggerIntersectionObserver (threshold 0.15) — runs once
Reduced-motionRespected — animation skipped
Pattern 02 — Body Reveal

Wave Rise · per-line

Main body paragraphs across the site (hero descriptions, section intros, case study overviews, contact subtitle). Each line emerges from a clipped mask, offset from below.

Live demo

I design digital products that make complex things feel simple. My work sits at the intersection of research, craft, and systems thinking — built on empathy for real users.

PropertyValue
Duration1800ms (--duration-longform)
Easing--ease-smooth (cubic-bezier(.19, 1, .22, 1))
Stagger0ms — all lines move together
OpacityNever changes — lines stay 100% visible behind mask
TriggerIntersectionObserver (threshold 0.15)
Pattern 03 — CTA Hover (per-letter)

Per-letter flip · the signature interaction

Applied to every link, button, and CTA across the site — navbar items, "View All", "View Case Study", "Send Message", footer email, filter chips. Per-letter, not per-word — each character is wrapped in its own mask and flips individually from white to accent yellow, with a staggered delay that creates the wave feel.

Hover me

View Projects →
PropertyValue
Unit of animation1 character (not word)
At-rest transition1300ms · --ease-out
On-hover transition250ms · --ease-out
Per-letter stagger20ms, capped at 400ms total
Color--text-primary → --accent
Reveal mechanicY-axis flip — original char slides up, accent clone slides up from below
Applied viasplit-hover.js + base.css .split-hover rules
Pattern 04 — Card Hover

Lift + Zoom + Title Shift

Blog cards, project cards, Next Project block. Card lifts 4px, thumbnail zooms 1.04x, title turns accent.

🎨

Hover me

ElementValue
Card lifttranslateY(-4px) · 350ms · --ease-out
Shadow12px 40px · 350ms
Thumbnail zoomscale(1.04) · 500ms · --ease-out
Title color200ms · ease
Pattern 05 — Infinite Scroll

Marquee · logos, testimonials background

Horizontal scrolling strips (client logos, decorative background text). Linear loop, pauses on hover.

PropertyValue
Duration28s (logos) / 32s (bgline)
Easing--ease-linear (the only linear use)
DirectionAlternating (logos-top right, logos-bottom left)
Pause on hoveranimation-play-state: paused

Motion rules

Design System v1 · Draft for review · Back to site